import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONString;
import org.json.JSONStringer;


/***********************************************************************
 * Artifact class
 * 
 * Implements the root of the artifact hierarchy
 *
 * Signature:
 *  public void install ();
 *  public void destroy ();
 *  public Coord position ();
 *  public String name ();
 *  public void report (String message);
 *  public void changePosition (Coord target);
 *  public boolean isOrbitable ();
 *  public void takeDamage (int damage);
 *  public abstract char display ();
 *  public abstract String toString ();
 ***********************************************************************/


public abstract class Artifact implements JSONString {

  private String name;
  private Coord position;

  protected Artifact (String n, Coord p) {
    this.name = Util.noSpaces(n);
    this.position = p;
  }
  
  public Artifact () {
    // Included so that fromJSON can be called without 
    // adding an object to the the map
  }
	
  public void install () { 
    Coord size = SpaceGame.map().size();
    SpaceGame.updateMap(Map.merge(Map.artifact(size.xPos(),
					       size.yPos(),this),
				  SpaceGame.map()));
  }	

  public void destroy () {
    SpaceGame.updateMap(SpaceGame.map().removeArtifact(this));
  }
	    

  public Coord position () {
    return this.position;
  }

  public String name () {
    return this.name;
  }

  public void report (String s) {
    if (SpaceGame.isGodMode())
      System.out.println(this.name() + " reports -- " + s);
  }

  public void changePosition (Coord c) {
    if (!c.within(Coord.create(0,0),
		  SpaceGame.map().size().move(-1,-1)))
      throw new IllegalArgumentException("Artifact.changePosition()");
    position = c;
  }

  public boolean isOrbitable () {
    return false;
  }

  public void takeDamage (int d) {
    report("no damage");
  }

  public abstract char display ();

  public abstract String toString ();

  public String toJSONString() {
    try {
      return new JSONStringer()
                        .object() 
                          .key("className")
                          .value("Artifact")
                          .key("name")
                          .value(this.name())
                          .key("position")
                          .value(this.position())
                        .endObject().toString();
    } catch (JSONException e) {
      e.printStackTrace();
      throw new RuntimeException("Unrecoverable JSON error, see above stack trace.");
    }
  }
  
  public static Artifact fromJSON(JSONObject json) {
    String classname;
    try {
      classname = json.getString("className");
    } catch (JSONException e) {
      e.printStackTrace();
      throw new RuntimeException("Unrecoverable JSON error, see above stack trace.");
    }
    if(classname.equals("Player")) {
      return Player.fromJSON(json);
    } else if(classname.equals("Ship")) {
      return Ship.fromJSON(json);
    } else if(classname.equals("Planet")) {
      return Planet.fromJSON(json);
    } else if(classname.equals("Star")) {
      return Star.fromJSON(json);
    } else if(classname.equals("Base")) {
      return Base.fromJSON(json);
    } else if(classname.equals("AutonomousEnemy")) {
      return AutonomousEnemy.fromJSON(json);
    } else {
      System.err.println("\"" + json.toString() + "\" does not represent an Artifact.");
      throw new RuntimeException("Cannot parse JSON, it is not an Artifact!");
    }
  }
}


